JavaScript kütüphaneleri için tip güvenliği ve otomatik tamamlama sağlamak üzere TypeScript bildirim dosyalarında (.d.ts) ustalaşın. @types kullanın ve üçüncü parti kodlarla profesyonelce çalışın.
JavaScript Ekosisteminin Kilidini Açmak: TypeScript Bildirim Dosyalarına Derinlemesine Bir Bakış
TypeScript, statik tiplemeyi JavaScript'in dinamik dünyasına getirerek modern web geliştirmede devrim yarattı. Bu tip güvenliği inanılmaz faydalar sağlar: hataları derleme zamanında yakalamak, güçlü editör otomatik tamamlama özelliklerini etkinleştirmek ve büyük kod tabanlarını önemli ölçüde daha sürdürülebilir hale getirmek. Ancak, mevcut JavaScript kütüphanelerinin geniş ekosistemini kullanmak istediğimizde büyük bir zorluk ortaya çıkar—bunların çoğu TypeScript ile yazılmamıştır. Katı tipli TypeScript kodumuz, tipsiz bir JavaScript kütüphanesindeki şekilleri, fonksiyonları ve değişkenleri nasıl anlar?
Cevap, TypeScript Bildirim Dosyaları'nda yatmaktadır. .d.ts uzantısıyla tanımlanabilen bu dosyalar, TypeScript ve JavaScript dünyaları arasındaki temel köprüdür. Bunlar, üçüncü parti bir kütüphanenin türlerini, gerçek uygulamasını içermeden tanımlayan bir şablon veya bir API sözleşmesi gibi hareket ederler. Bu kapsamlı rehberde, TypeScript projelerinizdeki herhangi bir JavaScript kütüphanesi için tip tanımlarını güvenle yönetmek için bilmeniz gereken her şeyi keşfedeceğiz.
TypeScript Bildirim Dosyaları Tam Olarak Nedir?
Farklı bir dil konuşan bir müteahhit tuttuğunuzu hayal edin. Onlarla etkili bir şekilde çalışmak için, ikinizin de anladığı bir dilde bir çevirmene veya ayrıntılı bir talimat setine ihtiyacınız olurdu. Bir bildirim dosyası, TypeScript derleyicisi (müteahhit) için tam olarak bu amaca hizmet eder.
Bir .d.ts dosyası yalnızca tip bilgisi içerir. Şunları içerir:
- Fonksiyonlar ve metotlar için imzalar (parametre tipleri, dönüş tipleri).
- Değişkenler ve tipleri için tanımlar.
- Karmaşık nesneler için arayüzler ve tip takma adları.
- Özellikleri ve metotları dahil olmak üzere sınıf tanımları.
- İsim alanı ve modül yapıları.
En önemlisi, bu dosyalar yürütülebilir kod içermez. Tamamen statik analiz içindirler. TypeScript projenize Lodash gibi bir JavaScript kütüphanesi import ettiğinizde, derleyici ilgili bir bildirim dosyası arar. Eğer bir tane bulursa, kodunuzu doğrulayabilir, akıllı otomatik tamamlama sağlayabilir ve kütüphaneyi doğru kullandığınızdan emin olabilir. Eğer bulamazsa, Could not find a declaration file for module 'lodash'. gibi bir hata verir.
Bildirim Dosyaları Neden Profesyonel Geliştirme İçin Tartışılmazdır
Bir TypeScript projesinde uygun tip tanımları olmadan JavaScript kütüphaneleri kullanmak, en başta TypeScript kullanma nedenini baltalar. Popüler yardımcı kütüphane Lodash'ı kullanarak basit bir senaryo düşünelim.
Tip Tanımları Olmayan Dünya
Bir bildirim dosyası olmadan, TypeScript'in lodash'in ne olduğu veya ne içerdiği hakkında hiçbir fikri yoktur. Kodu derlemek için bile, şöyle hızlı bir çözüm kullanmaya yönelebilirsiniz:
const _: any = require('lodash');
const users = [{ 'user': 'barney' }, { 'user': 'fred' }];
// Otomatik tamamlama? Burada yardım yok.
// Tip kontrolü? Hayır. 'username' doğru özellik mi?
// Derleyici buna izin verir, ancak çalışma zamanında başarısız olabilir.
_.find(users, { username: 'fred' });
Bu durumda, _ değişkeni any tipindedir. Bu, etkili bir şekilde TypeScript'e, "Bu değişkenle ilgili hiçbir şeyi kontrol etme" der. Tüm faydaları kaybedersiniz: otomatik tamamlama yok, argümanlar üzerinde tip kontrolü yok ve dönüş tipi hakkında kesinlik yok. Bu, çalışma zamanı hataları için bir üreme alanıdır.
Tip Tanımları Olan Dünya
Şimdi, gerekli bildirim dosyasını sağladığımızda ne olduğunu görelim. Tipleri yükledikten sonra (ki bunu bir sonraki bölümde ele alacağız), deneyim dönüşür:
import _ from 'lodash';
interface User {
user: string;
active?: boolean;
}
const users: User[] = [{ 'user': 'barney' }, { 'user': 'fred' }];
// 1. Editör 'find' ve diğer lodash fonksiyonları için otomatik tamamlama sağlar.
// 2. 'find' üzerine gelindiğinde tam imzasını ve dokümantasyonunu gösterir.
// 3. TypeScript, `users`'ın bir `User` nesneleri dizisi olduğunu görür.
// 4. TypeScript, `User[]` üzerindeki `find` için yüklemin `user` veya `active` içermesi gerektiğini bilir.
// DOĞRU: TypeScript mutlu.
const fred = _.find(users, { user: 'fred' });
// HATA: TypeScript hatayı yakalar!
// 'User' tipinde 'username' özelliği mevcut değil.
const betty = _.find(users, { username: 'betty' });
Fark gece ve gündüz gibidir. Tam tip güvenliği, araçlar sayesinde üstün geliştirici deneyimi ve potansiyel hatalarda dramatik bir azalma kazanırız. Bu, TypeScript ile çalışmak için profesyonel standarttır.
Tip Tanımlarını Bulma Hiyerarşisi
Peki, favori kütüphaneleriniz için bu sihirli .d.ts dosyalarını nasıl elde edersiniz? Senaryoların büyük çoğunluğunu kapsayan iyi kurulmuş bir süreç vardır.
Adım 1: Kütüphanenin Kendi Tiplerini Paketleyip Paketlemediğini Kontrol Edin
En iyi senaryo, bir kütüphanenin TypeScript ile yazılması veya bakımcılarının resmi bildirim dosyalarını aynı paket içinde sağlamasıdır. Bu, modern, iyi bakımlı projeler için giderek daha yaygın hale gelmektedir.
Nasıl kontrol edilir:
- Kütüphaneyi her zamanki gibi yükleyin:
npm install axios node_modules/axiosiçindeki kütüphane klasörüne bakın. Herhangi bir.d.tsdosyası görüyor musunuz?- Kütüphanenin
package.jsondosyasında bir"types"veya"typings"alanı olup olmadığını kontrol edin. Bu alan doğrudan ana bildirim dosyasına işaret eder. Örneğin, Axios'unpackage.jsondosyası şunu içerir:"types": "index.d.ts".
Bu koşullar karşılanıyorsa, işiniz bitti! TypeScript bu paketlenmiş tipleri otomatik olarak bulacak ve kullanacaktır. Başka bir işlem yapmanıza gerek yoktur.
Adım 2: DefinitelyTyped Projesi (@types)
Kendi tiplerini paketlemeyen binlerce JavaScript kütüphanesi için, küresel TypeScript topluluğu inanılmaz bir kaynak oluşturmuştur: DefinitelyTyped.
DefinitelyTyped, GitHub'da çok sayıda JavaScript paketi için yüksek kaliteli bildirim dosyalarını barındıran, merkezi, topluluk tarafından yönetilen bir depodur. Bu tanımlar, npm kayıt defterinde @types kapsamı altında yayınlanır.
Nasıl kullanılır:
Eğer lodash gibi bir kütüphane kendi tiplerini paketlemiyorsa, ilgili @types paketini bir geliştirme bağımlılığı olarak yüklersiniz:
npm install --save-dev @types/lodash
Adlandırma kuralı basit ve öngörülebilirdir: package-name adlı bir paket için, tipleri neredeyse her zaman @types/package-name adresinde olacaktır. Mevcut tipleri npm web sitesinde veya doğrudan DefinitelyTyped deposunda arayabilirsiniz.
Neden --save-dev? Bildirim dosyaları yalnızca geliştirme ve derleme sırasında gereklidir. Herhangi bir çalışma zamanı kodu içermezler, bu yüzden son üretim paketine dahil edilmemelidirler. Onları bir devDependency olarak yüklemek bu ayrımı sağlar.
Adım 3: Hiç Tip Olmadığında - Kendi Tiplerinizi Yazmak
Peki ya tipleri paketlemeyen ve DefinitelyTyped'de olmayan daha eski, niş veya şirket içi özel bir kütüphane kullanıyorsanız? Bu durumda, kolları sıvamanız ve kendi bildirim dosyanızı oluşturmanız gerekir. Bu göz korkutucu gelse de, basit başlayabilir ve gerektiğinde daha fazla ayrıntı ekleyebilirsiniz.
Hızlı Çözüm: Kısayol Ortam Modülü Bildirimi
Bazen, uygun bir tipleme stratejisi bulurken projenizin hatasız derlenmesini sağlamanız yeterlidir. Projenizde bir dosya oluşturabilir (ör. declarations.d.ts veya types/global.d.ts) ve bir kısayol bildirimi ekleyebilirsiniz:
// bir .d.ts dosyasında
declare module 'some-untyped-library';
Bu, TypeScript'e şöyle der: "İnan bana, 'some-untyped-library' adında bir modül var. Sadece ondan import edilen her şeyi any tipi olarak kabul et." Bu, derleyici hatasını susturur, ancak tartıştığımız gibi, o kütüphane için tüm tip güvenliğini feda eder. Bu, uzun vadeli bir çözüm değil, geçici bir yamadır.
Temel Bir Özel Bildirim Dosyası Oluşturma
Daha iyi bir yaklaşım, kütüphanenin gerçekten kullandığınız kısımları için tipleri tanımlamaya başlamaktır. string-utils adında tek bir fonksiyon ihraç eden basit bir kütüphanemiz olduğunu varsayalım.
// node_modules/string-utils/index.js içinde
module.exports.capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
Projemizin kök dizininde özel bir `types` dizininde bir string-utils.d.ts dosyası oluşturabiliriz.
// my-project/types/string-utils.d.ts içinde
declare module 'string-utils' {
export function capitalize(str: string): string;
// Kullandıkça buraya diğer fonksiyon tanımlarını ekleyebilirsiniz
// export function slugify(str: string): string;
}
Şimdi, TypeScript'e özel tip tanımlarımızı nerede bulacağını söylememiz gerekiyor. Bunu tsconfig.json dosyasında yaparız:
{
"compilerOptions": {
// ... diğer seçenekler
"baseUrl": ".",
"paths": {
"*": ["types/*"]
}
}
}
Bu kurulumla, import { capitalize } from 'string-utils' yaptığınızda, TypeScript özel bildirim dosyanızı bulacak ve tanımladığınız tip güvenliğini sağlayacaktır. Kütüphanenin daha fazla özelliğini kullandıkça bu dosyayı kademeli olarak oluşturabilirsiniz.
Daha Derine Dalmak: Bildirim Dosyaları Yazmak
Bildirim dosyalarını okurken veya yazarken karşılaşacağınız bazı daha gelişmiş kavramları keşfedelim.
Farklı Türde İhraçları Bildirme
JavaScript modülleri çeşitli yollarla bir şeyler ihraç edebilir. Bildirim dosyanız kütüphanenin ihraç yapısıyla eşleşmelidir.
- İsimlendirilmiş İhraçlar: Bu en yaygın olanıdır. Yukarıda `export function capitalize(...)` ile gördük. Ayrıca sabitleri, arayüzleri ve sınıfları da ihraç edebilirsiniz.
- Varsayılan İhraç: `export default` kullanan kütüphaneler için.
- UMD Global Değişkenleri: Bir
<script>etiketi aracılığıyla tarayıcılarda çalışmak üzere tasarlanmış eski kütüphaneler için, genellikle kendilerini global `window` nesnesine eklerler. Bu global değişkenleri bildirebilirsiniz. - `export =` ve `import = require()`: Bu sözdizimi, `module.exports = ...` kullanan eski CommonJS modülleri içindir. Örneğin, bir kütüphane `module.exports = myClass;` yaparsa.
declare module 'my-lib' {
export const version: string;
export interface Options { retries: number; }
export function doSomething(options: Options): Promise
declare module 'my-default-lib' {
// Bir fonksiyon varsayılan ihracı için
export default function myCoolFunction(): void;
// Bir nesne varsayılan ihracı için
// const myLib = { name: 'lib', version: '1.0' };
// export default myLib;
}
// Belirli bir tipte global bir '$' değişkeni bildirir
declare var $: JQueryStatic;
// my-class.d.ts içinde
declare class MyClass { constructor(name: string); }
export = MyClass;
// app.ts dosyanızda
import MyClass = require('my-class');
const instance = new MyClass('test');
Modern ES Modülleri ile daha az yaygın olsa da, bu, hala yaygın olarak kullanılan birçok eski Node.js paketiyle uyumluluk için kritiktir.
Modül Genişletme: Mevcut Tipleri Genişletme
En güçlü özelliklerden biri modül genişletme'dir (bildirim birleştirme olarak da bilinir). Bu, başka bir paketin bildirim dosyasında tanımlanan mevcut arayüzlere özellikler eklemenizi sağlar. Bu, Express veya Fastify gibi bir eklenti mimarisine sahip kütüphaneler için son derece kullanışlıdır.
Express'te `Request` nesnesine bir `user` özelliği ekleyen bir ara yazılım (middleware) kullandığınızı hayal edin. Genişletme olmadan, TypeScript `user`'ın `Request` üzerinde mevcut olmadığından şikayet edecektir.
İşte TypeScript'e bu yeni özellik hakkında nasıl bilgi vereceğiniz:
// types/express.d.ts dosyanızda
// Genişletmek için orijinal tipi import etmeliyiz
import { UserProfile } from './auth'; // UserProfile tipine sahip olduğunuzu varsayarsak
// TypeScript'e 'express-serve-static-core' modülünü genişlettiğimizi söylüyoruz
declare module 'express-serve-static-core' {
// O modül içindeki 'Request' arayüzünü hedefliyoruz
interface Request {
// Özel özelliğimizi ekliyoruz
user?: UserProfile;
}
}
Artık, uygulamanız boyunca Express `Request` nesnesi isteğe bağlı `user` özelliği ile doğru bir şekilde tiplenecek ve tam tip güvenliği ile otomatik tamamlama elde edeceksiniz.
Üçlü Eğik Çizgi Direktifleri
Bazen .d.ts dosyalarının en üstünde üç eğik çizgiyle (///) başlayan yorumlar görebilirsiniz. Bunlar, derleyici talimatları olarak işlev gören üçlü eğik çizgi direktifleridir.
/// <reference types="..." />: Bu en yaygın olanıdır. Başka bir paketin tip tanımlarını açıkça bir bağımlılık olarak ekler. Örneğin, bir WebdriverIO eklentisi için tipler, kendi tipleri çekirdek WebdriverIO tiplerine bağlı olduğu için/// <reference types="webdriverio" />içerebilir./// <reference path="..." />: Bu, aynı proje içindeki başka bir dosyaya bağımlılığı bildirmek için kullanılır. Bu, büyük ölçüde ES modül importları tarafından geçersiz kılınan daha eski bir sözdizimidir.
Bildirim Dosyalarını Yönetmek İçin En İyi Uygulamalar
- Paketlenmiş Tipleri Tercih Edin: Kütüphaneler arasında seçim yaparken, TypeScript ile yazılmış olanları veya kendi resmi tip tanımlarını paketleyenleri tercih edin. Bu, TypeScript ekosistemine bir bağlılık sinyalidir.
@types'ıdevDependencies'de Tutun:@typespaketlerini her zaman--save-devveya-Dile yükleyin. Üretim kodunuz için gerekli değillerdir.- Sürümleri Hizalayın: Yaygın bir hata kaynağı, kütüphane sürümü ile
@typessürümü arasındaki uyuşmazlıktır. Bir kütüphanedeki büyük bir sürüm artışı (örneğin, v2'den v3'e), API'sinde@typespaketine yansıtılması gereken köklü değişikliklere sahip olacaktır. Bunları senkronize tutmaya çalışın. - Kontrol İçin
tsconfig.jsonKullanın:tsconfig.jsondosyanızdakitypeRootsvetypesderleyici seçenekleri, TypeScript'in bildirim dosyalarını nerede arayacağı konusunda size ayrıntılı kontrol sağlayabilir.typeRoots, derleyiciye hangi klasörleri kontrol edeceğini söyler (varsayılan olarak./node_modules/@types'dır) vetypes, hangi tip paketlerinin dahil edileceğini açıkça listelemenize olanak tanır. - Geri Katkıda Bulunun: Sahip olmayan bir kütüphane için kapsamlı bir bildirim dosyası yazarsanız, bunu DefinitelyTyped projesine katkıda bulunmayı düşünün. Bu, küresel geliştirici topluluğuna geri vermenin ve binlerce kişiye yardım etmenin harika bir yoludur.
Sonuç: Tip Güvenliğinin İsimsiz Kahramanları
TypeScript Bildirim Dosyaları, JavaScript'in dinamik, genişleyen dünyasını sağlam, tip güvenli bir geliştirme ortamına sorunsuz bir şekilde entegre etmeyi mümkün kılan isimsiz kahramanlardır. Araçlarımızı güçlendiren, sayısız hatayı önleyen ve kod tabanlarımızı daha dayanıklı ve kendi kendini belgeleyen hale getiren kritik bağlantıdır.
Kendi .d.ts dosyalarınızı nasıl bulacağınızı, kullanacağınızı ve hatta oluşturacağınızı anlayarak, sadece bir derleyici hatasını düzeltmiyorsunuz—tüm geliştirme iş akışınızı yükseltiyorsunuz. Hem TypeScript'in hem de zengin JavaScript kütüphaneleri ekosisteminin tam potansiyelini ortaya çıkarıyor, küresel bir kitle için daha iyi, daha güvenilir yazılımlarla sonuçlanan güçlü bir sinerji yaratıyorsunuz.